package scatter.schedulequartz.rest.mapstruct;

import org.mapstruct.Mapper;
import org.mapstruct.ReportingPolicy;
import org.mapstruct.factory.Mappers;
import org.quartz.*;
import scatter.schedulequartz.pojo.form.JobCronAddForm;
import scatter.schedulequartz.pojo.form.JobCronUpdateForm;
import scatter.schedulequartz.pojo.form.ScheduleForm;
import scatter.schedulequartz.pojo.form.ScheduleQueryForm;
import scatter.schedulequartz.pojo.vo.*;

import java.util.List;
import java.util.stream.Collectors;

/**
 * Created by yangwei
 * Created at 2021/2/3 17:15
 */
@Mapper(componentModel = "spring",unmappedTargetPolicy = ReportingPolicy.IGNORE)
public interface ScheduleMapStruct {
    ScheduleMapStruct INSTANCE = Mappers.getMapper( ScheduleMapStruct.class );


    /**
     * scheduler 转 vo
     * @param scheduler
     * @return
     */
    default ScheduleVo mapScheduler(Scheduler scheduler) throws SchedulerException {
        ScheduleVo scheduleVo = new ScheduleVo();
        scheduleVo.setSchedulerName(scheduler.getSchedulerName());
        scheduleVo.setSchedulerInstanceId(scheduler.getSchedulerInstanceId());
        scheduleVo.setScheduleContextDataMap(scheduler.getContext());
        scheduleVo.setIsStarted(scheduler.isStarted());
        scheduleVo.setIsInStandbyMode(scheduler.isInStandbyMode());
        scheduleVo.setIsShutdown(scheduler.isShutdown());
        scheduleVo.setScheduleMetaData(mapSchedulerMetaData(scheduler.getMetaData()));
        scheduleVo.setTriggerListeners(mapTriggerListeners(scheduler.getListenerManager().getTriggerListeners()));
        scheduleVo.setJobListeners(mapJobListeners(scheduler.getListenerManager().getJobListeners()));
        scheduleVo.setScheduleListeners(mapScheduleListeners(scheduler.getListenerManager().getSchedulerListeners()));
        return scheduleVo;
    }

    /**
     * TriggerListeners 转vo
     * @param schedulerListeners
     * @return
     */
    default List<TriggerListenerVo> mapTriggerListeners(List<TriggerListener> schedulerListeners) {
        return schedulerListeners.stream().map(schedulerListener -> mapTriggerListener(schedulerListener)).collect(Collectors.toList());
    }

    /**
     * TriggerListener 转 vo
     * @param triggerListener
     * @return
     */
    default TriggerListenerVo mapTriggerListener(TriggerListener triggerListener) {
        TriggerListenerVo triggerListenerVo = new TriggerListenerVo();
        triggerListenerVo.setClassName(triggerListener.getClass().getName());
        triggerListenerVo.setName(triggerListener.getName());
        return triggerListenerVo;
    }
    /**
     * JobListeners 转vo
     * @param schedulerListeners
     * @return
     */
    default List<JobListenerVo> mapJobListeners(List<JobListener> schedulerListeners) {
        return schedulerListeners.stream().map(schedulerListener -> mapJobListener(schedulerListener)).collect(Collectors.toList());
    }

    /**
     * JobListener 转 vo
     * @param jobListener
     * @return
     */
    default JobListenerVo mapJobListener(JobListener jobListener) {
        JobListenerVo jobListenerVo = new JobListenerVo();
        jobListenerVo.setClassName(jobListener.getClass().getName());
        jobListenerVo.setName(jobListener.getName());
        return jobListenerVo;
    }
    /**
     * SchedulerListeners 转vo
     * @param schedulerListeners
     * @return
     */
    default List<ScheduleListenerVo> mapScheduleListeners(List<SchedulerListener> schedulerListeners) {
        return schedulerListeners.stream().map(schedulerListener -> mapScheduleListener(schedulerListener)).collect(Collectors.toList());
    }

    /**
     * SchedulerListener 转 vo
     * @param schedulerListener
     * @return
     */
    default ScheduleListenerVo mapScheduleListener(SchedulerListener schedulerListener) {
        ScheduleListenerVo scheduleListenerVo = new ScheduleListenerVo();
        scheduleListenerVo.setClassName(schedulerListener.getClass().getName());
        return scheduleListenerVo;
    }
    /**
     * SchedulerMetaData 转 vo
     * @param schedulerMetaData
     * @return
     */
    default ScheduleMetaDataVo mapSchedulerMetaData(SchedulerMetaData schedulerMetaData) {
        ScheduleMetaDataVo scheduleMetaDataVo = new ScheduleMetaDataVo();
        scheduleMetaDataVo.setSchedulerName(schedulerMetaData.getSchedulerName());
        scheduleMetaDataVo.setSchedulerInstanceId(schedulerMetaData.getSchedulerInstanceId());
        scheduleMetaDataVo.setSchedulerClassName(schedulerMetaData.getSchedulerClass().getName());
        scheduleMetaDataVo.setIsSchedulerRemote(schedulerMetaData.isSchedulerRemote());
        scheduleMetaDataVo.setIsStarted(schedulerMetaData.isStarted());
        scheduleMetaDataVo.setIsInStandbyMode(schedulerMetaData.isInStandbyMode());
        scheduleMetaDataVo.setIsShutdown(schedulerMetaData.isShutdown());
        scheduleMetaDataVo.setStartAt(schedulerMetaData.getRunningSince());
        scheduleMetaDataVo.setNumberOfJobsExecuted(schedulerMetaData.getNumberOfJobsExecuted());
        scheduleMetaDataVo.setJobStoreClassName(schedulerMetaData.getJobStoreClass().getName());
        scheduleMetaDataVo.setIsJobStoreSupportsPersistence(schedulerMetaData.isJobStoreSupportsPersistence());
        scheduleMetaDataVo.setIsJobStoreClustered(schedulerMetaData.isJobStoreClustered());
        scheduleMetaDataVo.setThreadPoolClassName(schedulerMetaData.getThreadPoolClass().getName());
        scheduleMetaDataVo.setThreadPoolSize(schedulerMetaData.getThreadPoolSize());
        scheduleMetaDataVo.setVersion(schedulerMetaData.getVersion());
        return scheduleMetaDataVo;
    }

    /**
     * Trigger 转 vo
     * @param trigger
     * @return
     */
    default TriggerVo mapTrigger(Trigger trigger, Scheduler scheduler) throws SchedulerException {
        TriggerVo triggerVo = new TriggerVo();
        triggerVo.setName(trigger.getKey().getName());
        triggerVo.setGroup(trigger.getKey().getGroup());
        triggerVo.setTriggerClassName(trigger.getClass().getName());
        triggerVo.setTriggerState(scheduler.getTriggerState(trigger.getKey()).name());
        triggerVo.setCalendarName(trigger.getCalendarName());
        triggerVo.setDescription(triggerVo.getDescription());
        triggerVo.setPriority(trigger.getPriority());
        triggerVo.setIsMayFireAgain(trigger.mayFireAgain());
        triggerVo.setStartAt(trigger.getStartTime());
        triggerVo.setEndAt(trigger.getEndTime());
        triggerVo.setNextFireAt(trigger.getNextFireTime());
        triggerVo.setPreviousFireAt(trigger.getPreviousFireTime());
        triggerVo.setFinalFireAt(trigger.getFinalFireTime());
        triggerVo.setMisfireInstruction(trigger.getMisfireInstruction());
        if (trigger instanceof CronTrigger) {
            triggerVo.setCronExpression(((CronTrigger) trigger).getCronExpression());
        }
        return triggerVo;
    }


    /**
     * JobDetail 转 vo
     * @param jobDetail
     * @return
     */
    default JobDetailVo mapJobDetail(JobDetail jobDetail) {
        JobDetailVo jobDetailVo = new JobDetailVo();
        jobDetailVo.setName(jobDetail.getKey().getName());
        jobDetailVo.setGroup(jobDetail.getKey().getGroup());
        jobDetailVo.setJobClassName(jobDetail.getJobClass().getName());
        jobDetailVo.setDescription(jobDetail.getDescription());
        jobDetailVo.setIsDurable(jobDetail.isDurable());
        jobDetailVo.setIsPersistJobDataAfterExecution(jobDetail.isPersistJobDataAfterExecution());
        jobDetailVo.setIsConcurrentExectionDisallowed(jobDetail.isConcurrentExectionDisallowed());
        jobDetailVo.setIsRecovery(jobDetail.requestsRecovery());
        jobDetailVo.setDataMap(jobDetail.getJobDataMap());
        return jobDetailVo;
    }

    public ScheduleForm map(JobCronAddForm addForm);
    public ScheduleForm map(JobCronUpdateForm updateForm);
    public JobCronAddForm mapUpdateToAddForm(JobCronUpdateForm updateForm);
    public ScheduleQueryForm map(ScheduleForm scheduleForm);
    public ScheduleForm map( ScheduleQueryForm scheduleForm);
    public JobDetailExtVo map( JobDetailVo jobDetailVo);
}
